#include <QtGui>

#include "filterDialog.h"
#include "filterPages.h"
#include "../src/data.h"

#define MAX 300

FilterDialog::FilterDialog(QWidget *_parent, QImage *_i) : QDialog(_parent), originalImage(_i){
    qDebug() << _i->format();
    if(_i->format() != QImage::Format_RGB32) testImage = new QImage(_i->convertToFormat(QImage::Format_RGB32));
    else testImage = new QImage(*_i);

    filter = new SpatialFilter(new Data(testImage->bits(), testImage->width(), testImage->height()));



    QSplitter *horizontalSplitter = new QSplitter(this);
    horizontalSplitter->setOrientation(Qt::Horizontal);
    QSplitter *verticalSplitter = new QSplitter(horizontalSplitter);
    verticalSplitter->setOrientation(Qt::Vertical);


    preview = new Image(verticalSplitter, testImage);
//    preview->setAreaSize(600, 400);

    contentsWidget = new QListWidget(horizontalSplitter);
//    contentsWidget->setViewMode(QListView::IconMode);
//    contentsWidget->setIconSize(QSize(50, 31));
//    contentsWidget->setMovement(QListView::Adjust);
    contentsWidget->setResizeMode(QListView::Adjust);
    contentsWidget->setMinimumWidth(200);
    contentsWidget->setMaximumWidth(300);
    contentsWidget->setSpacing(7);



    /*INCLUINDO AS PAGINAS*/
    pagesWidget = new QStackedWidget(verticalSplitter);
    pagesWidget->addWidget(new GrayScalePage);
    pagesWidget->addWidget(new NegativePage);
    pagesWidget->addWidget(new LogPage);

    PowerPage *pp = new PowerPage;
    pagesWidget->addWidget(pp);
    connect(pp, SIGNAL(done()), this, SLOT(powerFilter()));

    ThresholdingPage *tp = new ThresholdingPage;
    pagesWidget->addWidget(tp);
    connect(tp, SIGNAL(done()), this, SLOT(thresholdingFilter()));

    pagesWidget->addWidget(new HistogramEqualizationPage);

    HistogramMatchingPage *hmp = new HistogramMatchingPage;
    pagesWidget->addWidget(hmp);
    connect(hmp, SIGNAL(done()), this, SLOT(histogramMatchingFilter()));

    LocalHistogramProcessingPage *lhpp = new LocalHistogramProcessingPage;
    pagesWidget->addWidget(lhpp);
    connect(lhpp, SIGNAL(done()), this, SLOT(localHistogramProcessingFilter()));

    LocalHistogramProcessingWithStatisticsPage *lhpwsp = new LocalHistogramProcessingWithStatisticsPage;
    pagesWidget->addWidget(lhpwsp);
    connect(lhpwsp, SIGNAL(done()), this, SLOT(localHistogramProcessingWithStatisticsFilter()));

    AveragePage *ap = new AveragePage;
    pagesWidget->addWidget(ap);
    connect(ap, SIGNAL(done()), this, SLOT(averageFilter()));

    WeightedAveragePage *wap = new WeightedAveragePage;
    pagesWidget->addWidget(wap);
    connect(wap, SIGNAL(done()), this, SLOT(weightedAverageFilter()));

    GaussianPage *gp = new GaussianPage;
    pagesWidget->addWidget(gp);
    connect(gp, SIGNAL(done()), this, SLOT(gaussianFilter()));

    OrderStatisticPage *osp = new OrderStatisticPage;
    pagesWidget->addWidget(osp);
    connect(osp, SIGNAL(done()), this, SLOT(orderStatisticFilter()));

    LaplacianPage *lp = new LaplacianPage;
    pagesWidget->addWidget(lp);
    connect(lp, SIGNAL(done()), this, SLOT(laplacianFilter()));

    UnsharpMaskingAndHighboostPage *umahp = new UnsharpMaskingAndHighboostPage;
    pagesWidget->addWidget(umahp);
    connect(umahp, SIGNAL(done()), this, SLOT(unsharpMaskingAndHighboostFilter()));

    GradientPage *grp = new GradientPage;
    pagesWidget->addWidget(grp);
    connect(grp, SIGNAL(done()), this, SLOT(gradientFilter()));





    QPushButton *closeButton = new QPushButton(tr("Fechar"));
    QPushButton *applyButton = new QPushButton(tr("Aplicar"));

    connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(applyButton, SIGNAL(clicked()), this, SLOT(apply()));

    createIcons();
    contentsWidget->setCurrentRow(0);


    verticalSplitter->addWidget(preview);
    verticalSplitter->addWidget(pagesWidget);
    horizontalSplitter->addWidget(contentsWidget);
    horizontalSplitter->addWidget(verticalSplitter);

    resize(600, 500);

    QHBoxLayout *buttonsLayout = new QHBoxLayout;
    buttonsLayout->addStretch(1);
    buttonsLayout->addWidget(applyButton);
    buttonsLayout->addWidget(closeButton);


    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(horizontalSplitter);
    mainLayout->addLayout(buttonsLayout);
    setLayout(mainLayout);

    setWindowTitle(tr("Galeria de Filtros"));
}

FilterDialog::~FilterDialog(){
}

void FilterDialog::createIcons(){
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(GRAYSCALE));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(NEGATIVE));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(LOG));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(POWER));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(THRESHOLDING));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(HISTOGRAM_EQUALIZATION));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(HISTOGRAM_MATCHING));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(LOCAL_HISTOGRAM_PROCESSING));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(LOCAL_HISTOGRAM_PROCESSING_WITH_STATISTICS));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(AVERAGE));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(WEIGHTED_AVERAGE));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(GAUSSIAN));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(ORDER_STATISTIC));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(LAPLACIAN));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(UNSHARP_MASKING_AND_HIGHBOOST_FILTERING));
    addButton(new QListWidgetItem(contentsWidget), "images/sem_ico.png", QString::fromUtf8(GRADIENT));

    connect(contentsWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
        this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*)));
}

void FilterDialog::addButton(QListWidgetItem *_button, QString _ico, QString _name){
//    _button->setIcon(QIcon(_ico));
    _button->setText(_name);
    _button->setTextAlignment(Qt::AlignLeft | Qt::AlignBottom);
    _button->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
}

void FilterDialog::apply(){
//    if(originalImage) delete originalImage;

    emit done(new QImage(*testImage));
    emit done();
    accept();
}

void FilterDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous){
    if (!current)
        current = previous;

    pagesWidget->setCurrentIndex(contentsWidget->row(current));


    revert();

    if(current->text() == QString(GRAYSCALE)){
        ((SpatialFilter*)filter)->grayScaleFilter();
        pagesWidget->hide();
    }else if(current->text() == QString(NEGATIVE)){
        ((SpatialFilter*)filter)->negativeFilter();
        pagesWidget->hide();
    }else if(current->text() == QString(LOG)){
        ((SpatialFilter*)filter)->logFilter(1.0);
        pagesWidget->hide();
    }else if(current->text() == QString::fromUtf8(POWER)){
        powerFilter();
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(THRESHOLDING)){
        thresholdingFilter();
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(HISTOGRAM_EQUALIZATION)){
        ((SpatialFilter*)filter)->histogramEqualizationFilter();
        pagesWidget->hide();
    }else if(current->text() == QString::fromUtf8(HISTOGRAM_MATCHING)){
        histogramMatchingFilter();
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(LOCAL_HISTOGRAM_PROCESSING)){
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(LOCAL_HISTOGRAM_PROCESSING_WITH_STATISTICS)){
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(AVERAGE)){
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(WEIGHTED_AVERAGE)){
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(GAUSSIAN)){
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(ORDER_STATISTIC)){
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(LAPLACIAN)){
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(UNSHARP_MASKING_AND_HIGHBOOST_FILTERING)){
        pagesWidget->show();
    }else if(current->text() == QString::fromUtf8(GRADIENT)){
        pagesWidget->show();
    }

//    pagesWidget->show();

    update();
}

void FilterDialog::powerFilter(){
    revert();

    PowerPage *pp = (PowerPage *)pagesWidget->currentWidget();
    ((SpatialFilter*)filter)->powerFilter(1.0, pp->getGamma());

    update();
}

void FilterDialog::thresholdingFilter(){
    revert();

    ThresholdingPage *tp = (ThresholdingPage *)pagesWidget->currentWidget();
    ((SpatialFilter*)filter)->thresholdingFilter(tp->getThreshold());

    update();
}

void FilterDialog::histogramMatchingFilter(){
    revert();

    HistogramMatchingPage *hmp = (HistogramMatchingPage *)pagesWidget->currentWidget();
    ((SpatialFilter*)filter)->histogramMatchingFilter(Histogram());

    update();
}

void FilterDialog::localHistogramProcessingFilter(){
    revert();

    LocalHistogramProcessingPage *lhpp = (LocalHistogramProcessingPage *)pagesWidget->currentWidget();
    Mask mask(lhpp->getM(), lhpp->getN());
    Data *d = ((SpatialFilter*)filter)->localHistogramProcessingFilter(&mask);
    delete testImage;
    testImage = new QImage(d->getData(), d->getWidth(), d->getHeight(), d->getWidth()*4, testImage->format());

    update();

    lhpp->tryItAgain();
}

void FilterDialog::localHistogramProcessingWithStatisticsFilter(){
    revert();

    LocalHistogramProcessingWithStatisticsPage *lhpwsp = (LocalHistogramProcessingWithStatisticsPage *)pagesWidget->currentWidget();
    Mask mask(lhpwsp->getM(), lhpwsp->getN());
    Data *d = ((SpatialFilter*)filter)->localHistogramProcessingWithStatisticsFilter(&mask, lhpwsp->getK0(), lhpwsp->getK1(), lhpwsp->getK2(), lhpwsp->getE());
    delete testImage;
    testImage = new QImage(d->getData(), d->getWidth(), d->getHeight(), d->getWidth()*4, testImage->format());

    update();

    lhpwsp->tryItAgain();
}

void FilterDialog::averageFilter(){
    revert();

    AveragePage *ap = (AveragePage *)pagesWidget->currentWidget();
    Mask mask(ap->getM(), ap->getN());
    Data *d = ((SpatialFilter*)filter)->correlation(&mask);
    delete testImage;
    testImage = new QImage(d->getData(), d->getWidth(), d->getHeight(), d->getWidth()*4, testImage->format());

    update();

    ap->tryItAgain();
}

void FilterDialog::weightedAverageFilter(){
    revert();

    WeightedAveragePage *wap = (WeightedAveragePage *)pagesWidget->currentWidget();
    Mask mask(wap->getM(), wap->getN());
    mask.weightedAverage();
    Data *d = ((SpatialFilter*)filter)->correlation(&mask);
    delete testImage;
    testImage = new QImage(d->getData(), d->getWidth(), d->getHeight(), d->getWidth()*4, testImage->format());

    update();

    wap->tryItAgain();
}

void FilterDialog::gaussianFilter(){
    revert();

    GaussianPage *gp = (GaussianPage *)pagesWidget->currentWidget();
    Mask mask(gp->getM(), gp->getN());
    mask.gaussian(gp->getSigma());
    Data *d = ((SpatialFilter*)filter)->correlation(&mask);
    delete testImage;
    testImage = new QImage(d->getData(), d->getWidth(), d->getHeight(), d->getWidth()*4, testImage->format());

    update();

    gp->tryItAgain();
}

void FilterDialog::orderStatisticFilter(){
    revert();

    OrderStatisticPage *osp = (OrderStatisticPage *)pagesWidget->currentWidget();
    Mask mask(osp->getM(), osp->getN());
    int position = osp->getPosition();
    Data *d = ((SpatialFilter*)filter)->orderStaticFilter(&mask, position);
    delete testImage;
    testImage = new QImage(d->getData(), d->getWidth(), d->getHeight(), d->getWidth()*4, testImage->format());

    update();

    osp->tryItAgain();
}

void FilterDialog::laplacianFilter(){
    revert();

    LaplacianPage *lp = (LaplacianPage *)pagesWidget->currentWidget();
    Mask mask(3, 3);
    mask.laplacian(lp->getType1(), lp->getType2());
    Data *d = ((SpatialFilter*)filter)->correlation(&mask);
    delete testImage;
    testImage = new QImage(d->getData(), d->getWidth(), d->getHeight(), d->getWidth()*4, testImage->format());

    update();

    lp->tryItAgain();
}

void FilterDialog::unsharpMaskingAndHighboostFilter(){
    revert();

    UnsharpMaskingAndHighboostPage *umahp = (UnsharpMaskingAndHighboostPage *)pagesWidget->currentWidget();
    Mask mask(umahp->getM(), umahp->getN());
    switch(umahp->getType()){
        case 0:{ //media
            // a mascara ja vem pronta
            break;
        }
        case 1:{ //media ponderada
            mask.weightedAverage();
            break;
        }
        case 3:{ //gaussiano
            mask.gaussian(umahp->getSigma());
            break;
        }
    }
    Data *d = ((SpatialFilter*)filter)->unsharpMaskingAndHighboostFilter(&mask);
    delete testImage;
    testImage = new QImage(d->getData(), d->getWidth(), d->getHeight(), d->getWidth()*4, testImage->format());

    update();

    umahp->tryItAgain();
}

void FilterDialog::gradientFilter(){
    revert();

    GradientPage *grp = (GradientPage *)pagesWidget->currentWidget();
    Data *d = NULL;
    switch(grp->getType()){
        case 0:{ //robert
            d = ((SpatialFilter*)filter)->robertFilter();
            break;
        }
        case 1:{ //sobel
            d = ((SpatialFilter*)filter)->sobelFilter();
            break;
        }
    }
    delete testImage;
    testImage = new QImage(d->getData(), d->getWidth(), d->getHeight(), d->getWidth()*4, testImage->format());

    update();

    grp->tryItAgain();
}

void FilterDialog::update(){
    preview->update(testImage);
}

void FilterDialog::revert(){
    delete testImage;
    testImage = new QImage(*originalImage);
    filter->getData()->setAll(testImage->bits(), testImage->width(), testImage->height());
}

void FilterDialog::changeFilter(QString _filter){
    for(int i = 0; i < contentsWidget->count(); i++){
        if(contentsWidget->item(i)->text() == _filter){
            contentsWidget->setCurrentRow(i);
            return;
        }
    }
}
